from django.utils.translation import gettext_lazy, gettext as _
from django.utils.functional import lazy
from rest_framework.permissions import IsAuthenticated
from rest_framework.serializers import Serializer, DateTimeField as DRFDateTimeField
from rest_framework.response import Response
from rest_framework.decorators import action
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi

from core import errors
from apps.api.paginations import NewPageNumberPagination100
from apps.api.viewsets import NormalGenericViewSet

from apps.app_kunyuan.models import KunYuanService
from apps.app_kunyuan import serializers
from apps.app_kunyuan.managers.kunyuan import KunYuanServiceManager
from apps.app_service.odc_manager import OrgDataCenterManager


class KunYuanServiceViewSet(NormalGenericViewSet):
    permission_classes = [IsAuthenticated, ]
    pagination_class = NewPageNumberPagination100
    lookup_field = 'id'

    @swagger_auto_schema(
        tags=['kunyuan'],
        operation_summary=gettext_lazy('列举坤元服务单元'),
        manual_parameters=[
            openapi.Parameter(
                name='status',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=False,
                description=lazy(str, str)(KunYuanService.Status.choices)
            ),
            openapi.Parameter(
                name='id',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=False,
                description=gettext_lazy('id查询')
            ),
        ],
        responses={
            200: ''''''
        }
    )
    def list(self, request, *args, **kwargs):
        """
        列举坤元服务单元

            http code 200:
            {
              "count": 1,
              "page_num": 1,
              "page_size": 100,
              "results": [
                {
                  "name": "36.33开发环境",
                  "name_en": "36.33 develop",
                  "endpoint_url": "http://xx.xx.xx.xx:8001",
                  "username": "",
                  "creation_time": "2024-11-14T07:50:40.099867Z",
                  "status": "enable",   # enable(服务中);disable(停止服务);deleted(删除)
                  "remarks": "",
                  "longitude": 0,
                  "latitude": 0,
                  "sort_weight": 0,
                  "version": "v3.2.0",
                  "version_update_time": "2024-11-14T08:21:42.824645Z",
                  "org_data_center": {
                    "id": "gii8wpgvtna8xvujhkf3496qo",
                    "name": "AIOps数据中心",
                    "name_en": "AIOps data center",
                    "longitude": 116.34334,
                    "latitude": 39.99288,
                    "sort_weight": -1008,
                    "organization": {
                      "id": "1",
                      "name": "中国科学院计算机网络信息中心",
                      "name_en": "Computer Network Information Center,  Chinese Academy of Sciences",
                      "sort_weight": -1
                    }
                  }
                }
              ]
            }
        """
        status = request.query_params.get('status', None)
        service_id = request.query_params.get('id', None)

        try:
            if status and status not in KunYuanService.Status.values:
                raise errors.InvalidArgument(message=_('无效的状态类型'))

            queryset = KunYuanService.objects.select_related('org_data_center__organization').all()
            if status:
                queryset = queryset.filter(status=status)

            if service_id:
                queryset = queryset.filter(id=service_id)

            objs = self.paginate_queryset(queryset)
            serializer = self.get_serializer(objs, many=True)
            return self.get_paginated_response(serializer.data)
        except Exception as exc:
            return self.exception_response(exc=exc)

    @swagger_auto_schema(
        tags=['kunyuan'],
        operation_summary=gettext_lazy('列举有管理员权限的坤元服务单元'),
        manual_parameters=[
            openapi.Parameter(
                name='status',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=False,
                description=lazy(str, str)(KunYuanService.Status.choices)
            ),
            openapi.Parameter(
                name='id',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=False,
                description=gettext_lazy('id查询')
            ),
            openapi.Parameter(
                name='with_admin_users',
                type=openapi.TYPE_STRING,
                in_=openapi.IN_QUERY,
                required=False,
                description=gettext_lazy('要求返回数据包含管理员信息，此参数不需要值')
            ),
        ],
        responses={
            200: ''''''
        }
    )
    @action(methods=['get'], detail=False, url_path='admin', url_name='admin-list')
    def list_admin_services(self, request, *args, **kwargs):
        """
        列举有管理员权限的坤元服务单元

            http code 200:
            {
              "count": 1,
              "page_num": 1,
              "page_size": 100,
              "results": [
                {
                  "name": "36.33开发环境",
                  "name_en": "36.33 develop",
                  "endpoint_url": "http://xx.xx.xx.xx:8001",
                  "username": "",
                  "creation_time": "2024-11-14T07:50:40.099867Z",
                  "status": "enable",
                  "remarks": "",
                  "longitude": 0,
                  "latitude": 0,
                  "sort_weight": 0,
                  "version": "v3.2.0",
                  "version_update_time": "2024-11-14T08:21:42.824645Z",
                  "org_data_center": {
                    "id": "gii8wpgvtna8xvujhkf3496qo",
                    "name": "AIOps数据中心",
                    "name_en": "AIOps data center",
                    "longitude": 116.34334,
                    "latitude": 39.99288,
                    "sort_weight": -1008,
                    "organization": {
                      "id": "1",
                      "name": "中国科学院计算机网络信息中心",
                      "name_en": "Computer Network Information Center,  Chinese Academy of Sciences",
                      "sort_weight": -1
                    }
                  },
                  "admin_users":[   # 使用参数 with_admin_users 时包含此数据
                    {"id": "xxx", "username": "xxxx", "role": "admin"}  # role: admin(管理员)，ops(运维管理员)
                  ]
                }
              ]
            }
        """
        status = request.query_params.get('status', None)
        service_id = request.query_params.get('id', None)
        with_admin_users = request.query_params.get('with_admin_users', None)

        try:
            if status and status not in KunYuanService.Status.values:
                raise errors.InvalidArgument(message=_('无效的状态类型'))

            user_id = request.user.id
            queryset = KunYuanService.objects.select_related(
                'org_data_center__organization'
            ).filter(
                org_data_center__users__id=user_id
            ).distinct()

            if status:
                queryset = queryset.filter(status=status)

            if service_id:
                queryset = queryset.filter(id=service_id)

            objs = self.paginate_queryset(queryset)
            if with_admin_users is not None:
                self.services_mixin_admins(services=objs)
                serializer = serializers.KunYuanServiceAdminSerializer(objs, many=True)
            else:
                serializer = serializers.KunYuanServiceSerializer(objs, many=True)

            return self.get_paginated_response(serializer.data)
        except Exception as exc:
            return self.exception_response(exc=exc)

    @swagger_auto_schema(
        tags=['kunyuan'],
        operation_summary=gettext_lazy('查询坤元服务版本'),
        manual_parameters=[
            openapi.Parameter(
                name='status',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=False,
                description=lazy(str, str)(KunYuanService.Status.choices)
            ),
        ],
        responses={
            200: ''''''
        }
    )
    @action(methods=['GET'], detail=True, url_path='version', url_name='version')
    def query_version(self, request, *args, **kwargs):
        """
        查询坤元服务版本

            * 实时去查询坤元服务，查询失败会返回错误信息

            http code 200:
            {
                "version": "v3.2.0",
                "version_update_time": "2024-11-14T08:21:42.824645Z"
            }
        """
        try:
            service = KunYuanService.objects.filter(id=kwargs[self.lookup_field]).first()
            if service is None:
                raise errors.TargetNotExist(message=_('坤元服务不存在'))

            r = KunYuanServiceManager.update_service_version(service=service)
            if r is not True:
                raise r
        except Exception as exc:
            return self.exception_response(exc=exc)

        return Response(data={
            'version': service.version,
            'version_update_time': DRFDateTimeField().to_representation(service.version_update_time)
        }, status=200)

    @staticmethod
    def services_mixin_admins(services: list):
        """
        给服务单元添加管理员列表属性
        """
        service_ids = []
        odc_ids = []
        for sv in services:
            service_ids.append(sv.id)
            if sv.org_data_center_id not in odc_ids:
                odc_ids.append(sv.org_data_center_id)

        odc_admins_map = {}
        if odc_ids:
            odc_admins_map = OrgDataCenterManager.get_odc_admins_map(odc_ids=odc_ids)

        for sv in services:
            admin_dict = {}
            ops_dict = {}
            if sv.org_data_center_id in odc_admins_map:
                odc_admins = odc_admins_map[sv.org_data_center_id]
                for u_id, u in odc_admins.items():
                    if u['role'] == 'admin':
                        admin_dict[u_id] = u
                    else:
                        ops_dict[u_id] = u

            sv.admin_users = list(admin_dict.values()) + list(ops_dict.values())

    def get_serializer_class(self):
        if self.action == 'list':
            return serializers.KunYuanServiceSerializer

        return Serializer
